<?php


namespace app\api\controller;


use app\api\ErrorCode;
use app\api\model\User;
use app\BaseController;
use app\common\model\Place;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\facade\Log;
use think\Response;

class Base
{

    protected $checkTokenOpen = false;//是否校验token
    protected $checkApiSignOpen = true;//是否签名
    public $user;//用户


    public function __construct()
    {
        Log::record("---------------------------", "info");
        Log::record($_SERVER['REQUEST_METHOD'] . '  ' . getUrl(), 'info');
        Log::record('REFERER  ' . (array_key_exists('HTTP_REFERER', $_SERVER) ? $_SERVER['HTTP_REFERER'] : ""), 'info');
        Log::record('GET  ' . json_encode($_GET, JSON_UNESCAPED_UNICODE), 'info');
        Log::record('POST  ' . json_encode($_POST, JSON_UNESCAPED_UNICODE), 'info');
        Log::record('cookie  ' . json_encode($_COOKIE, JSON_UNESCAPED_UNICODE), 'info');
        Log::record('input  ' . json_encode(input('param.'), JSON_UNESCAPED_UNICODE), 'info');
        if ($this->checkApiSignOpen) {
            $this->checkApiSign();
        }

        if ($this->checkTokenOpen) {
            $this->checkToken();
        }
    }


    /**
     * 获取token
     * @return array|mixed|string|null
     */
    protected function getToken()
    {
        $token = null;
        if (!$token) {
            //from header
            $token = request()->header("token");
        }
        if (!$token) {
            //from url
            $token = input("token");
        }
        return $token;
    }

    /**
     * 检测token
     * token规则
     * token由base64编码，解码后分为密文、主键、过期时间（时间戳）三部分，用竖线|隔开
     */
    public function checkToken()
    {
        $token = $this->getToken();
        if (!$token) {
            $this->error(ErrorCode::getError(ErrorCode::CODE_TOKEN_NONE), ErrorCode::CODE_TOKEN_NONE);
        }
        $tokerReal = base64_decode($token);
        $tokenArr = explode("|", $tokerReal);//拆分token

        if (count($tokenArr) != 3) {
            $this->error(ErrorCode::getError(ErrorCode::CODE_TOKEN_FORMAT_ERR), ErrorCode::CODE_TOKEN_FORMAT_ERR);
        }
        //判断token有没有超时
        if (time() > $tokenArr[2]) {
            $this->error(ErrorCode::getError(ErrorCode::CODE_TOKEN_EXPIRE), ErrorCode::CODE_TOKEN_EXPIRE);
        }
        //以下部分根据自己的业务实现

        //$field = "id,login_name,valid,last_login_time,login_count,token";
        $user = \app\common\model\User::where("token", "=", $token)->find();//找到token
        if (!$user) {
            $this->error(ErrorCode::getError(ErrorCode::CODE_TOKEN_ERR), ErrorCode::CODE_TOKEN_ERR);
        }
        $this->user = $user;

    }

    /**
     * 返回成功信息
     * @param $data
     * @param string $msg
     */
    public function success($data, $msg = "")
    {

        $res = returnFormat(0, $msg, $data);

        Log::record("response:" . mb_substr(json_encode($res, JSON_UNESCAPED_UNICODE), 0, 1000) . ",code:0", "debug");
        throw new HttpResponseException(Response::create($res, "json"));
    }

    /**
     * 简易错误提示
     * @param $code
     */
    public function errorSimple($code)
    {
        $this->error(ErrorCode::getError($code), $code);
    }

    /**
     * 返回失败信息
     * @param $msg
     * @param int $code
     * @param array $data
     */
    public function error($msg, $code = 999, $data = [])
    {
        $res = returnFormat($code, $msg, $data);
        Log::record("response:" . mb_substr(json_encode($res, JSON_UNESCAPED_UNICODE), 0, 1000) . ",code:" . $code, "debug");
        throw new HttpResponseException(Response::create($res, "json"));
    }

    /**
     * 自动校验
     * @param $class
     * @param $param
     */
    public function autoValid($class, $param)
    {
        try {
            validate($class)->check($param);
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            $this->error($e->getError());
        }
    }

    /**
     * 检查签名
     */
    public function checkApiSign()
    {

        $timestampLimit = 20;
        $param = request()->param();

        $this->autoValid([
            "_timestamp" => "require",
            "_sign" => "require",
        ], $param);
        if (!($param["_timestamp"] >= time() - $timestampLimit * 60 && $param["_timestamp"] <= time() + $timestampLimit * 60)) {
            $this->error("时间戳不合法，请刷新");
        }
        $sign = $param["_sign"];
        unset($param["_sign"]);
        ksort($param);

        $param['_timestamp'] = $param['_timestamp'];
        $secret = config("common.api_sign_secret");
        $signStr = stripslashes(json_encode($param, JSON_UNESCAPED_UNICODE) . $secret);

        $sign2 = md5($signStr);

        if ($sign !== $sign2) {
            Log::record("签名错误：sign: $sign sign2: $sign2", "debug");
            Log::record("sign2 签名key：" . $secret, "debug");
            Log::record("sign2 签名字符串：" . $signStr, "debug");
            $this->error("签名错误。" . $signStr);
        }
    }
}